﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using SistemaCenterQuimPost.Control;  //usado para validar datos.
using SistemaCenterQuimPost.Plantillas; //necesario para obtener fecha, nombre usuario etc,

namespace SistemaCenterQuimPost.UI.PostCajero
{
    public partial class frmRegistrarGastos : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {

        //-----------ATRIBUTOS----------------------
        private DataSet2 centerQuimDs;                               //atributos que me permiten obtener datos de BD.
        private DataSet2TableAdapters.GastosTableAdapter GastosTa;
        private DataSet2TableAdapters.CajasTableAdapter CajasTa;

        private int nroCaja;        //almacenará el numero de caja sobre la cual impactan los gastos.

        private string turno;        //almacenamos el turno de la caja actualmente abierta.

        private bool refrescarCenterQuimDs;        //controla si se debe acceder a la base de datos para actualizar el DataSet

        private string estFormulario;

        //----------CONSTRUCTORES-----------------

        public frmRegistrarGastos()
        {
            InitializeComponent();

            centerQuimDs = new DataSet2();                             //inicializacion de atributos que me permiten obtener datos de BD.
            GastosTa = new DataSet2TableAdapters.GastosTableAdapter();
            CajasTa = new DataSet2TableAdapters.CajasTableAdapter();

            nroCaja = 0;                         //Se inicializa el numero de caja con un valor arbitrario.

            refrescarCenterQuimDs = true;           //La primera vez debe refrescar el CenterQuimDs

            estFormulario = "";
        }


        //----------ESTADOS----------------

        private void frmRegistrarGastos_Load(object sender, EventArgs e)
        {

        }

        private void estEsperandoOperacion()  //estado cuando se inicia la interface, luego de llenar_dgv
        {
            this.cargarGrillaGastos();  //Se cargan los gastos si existieran.

            if (dgvGastos.RowCount == 0)  //luego de Llenar_dgv, no existe gastos
            {
                System.Windows.Forms.Control[] controlesHabilitados = { this.btnAgregar };
                System.Windows.Forms.Control[] controlesDeshabilitados = { this.dgvGastos, this.btnEditar, this.btnEliminar, this.btnRegistrar };
                System.Windows.Forms.Control[] controlesVisibles = { };
                System.Windows.Forms.Control[] controlesInvisibles = { lblConcepto, txtConcepto, this.lblImporte, this.txtImporte, lblErrorConcepto, lblErrorImporte, lblError };

                habilitarControles(controlesHabilitados);
                deshabilitarControles(controlesDeshabilitados);
                visibleControles(controlesVisibles);
                invisibleControles(controlesInvisibles);


            }
            else          //luego de Llenar_dg, existe al menos
            {
                System.Windows.Forms.Control[] controlesHabilitados = { this.btnAgregar, this.btnEditar, btnEliminar, this.dgvGastos };
                System.Windows.Forms.Control[] controlesDeshabilitados = { this.btnRegistrar };
                System.Windows.Forms.Control[] controlesVisibles = { };
                System.Windows.Forms.Control[] controlesInvisibles = { lblConcepto, txtConcepto, this.lblImporte, this.txtImporte, lblErrorConcepto, lblErrorImporte, lblError };

                habilitarControles(controlesHabilitados);
                deshabilitarControles(controlesDeshabilitados);
                visibleControles(controlesVisibles);
                invisibleControles(controlesInvisibles);

            }

            estFormulario = "estEsperandoOperacion";

            errorProvider1.Clear();

            dgvGastos.Focus();


        }

        private void estAgregar()  //estado cuando se presiona en agregar un gasto.
        {
            System.Windows.Forms.Control[] controlesHabilitados = { this.btnAgregar, this.btnRegistrar };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.dgvGastos, this.btnEditar, this.btnEliminar };
            System.Windows.Forms.Control[] controlesVisibles = { this.lblConcepto, this.txtConcepto, this.lblImporte, this.txtImporte, this.lblErrorConcepto, this.lblErrorImporte };
            System.Windows.Forms.Control[] controlesInvisibles = { lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            estFormulario = "estAgregar";

            txtConcepto.Text = "";  //borramos los datos.
            txtImporte.Text = "";

            errorProvider1.Clear();

            dgvGastos.Focus();

        }

        private void estEditar()  //estado cuando se presiona en agregar un gasto.
        {
            System.Windows.Forms.Control[] controlesHabilitados = { this.btnEditar, this.btnRegistrar };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.dgvGastos, this.btnAgregar, this.btnEliminar };
            System.Windows.Forms.Control[] controlesVisibles = { this.lblConcepto, this.txtConcepto, this.lblImporte, this.txtImporte, this.lblErrorConcepto, this.lblErrorImporte };
            System.Windows.Forms.Control[] controlesInvisibles = { lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            estFormulario = "estEditar";

            txtConcepto.Text = dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[1].Value.ToString();
            txtImporte.Text = dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[2].Value.ToString();

            errorProvider1.Clear();

            dgvGastos.Focus();

        }


        //---------METODOS VARIOS

        public void verificarCajaAbierta()  //Verifica que exista caja y que esté abierta, es llamado desde el menu.
        {
            try
            {
                int codUltimaCaja = 0;  //almacenará el código de la última caja, si existe.

                codUltimaCaja = Convert.ToInt32(CajasTa.ScalarQueryCaja()); //busca la ultima caja si hay registros.

                CajasTa.FillByNroCaja(centerQuimDs.Cajas, codUltimaCaja); //obtiene todos los datos de la ultima caja


                if (centerQuimDs.Cajas[0].estado == "A") // si la caja está abierta 
                {
                    this.nroCaja = centerQuimDs.Cajas[0].nroCaja; //establece el valor del atributo de instancia.

                    this.turno = centerQuimDs.Cajas[0].turno;

                    this.estEsperandoOperacion();  //deja el formulario como debe ser

                    this.Show();  //muestra la interface

                }

                else   //Si existe caja y está cerrada, informamos que no se procesar gastos hasta que habra alguna.
                {
                    MessageBox.Show("No existe caja abierta, en la que pueda registrar gastos.", "INFORMES", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    this.Close(); //Cerramos el form instanciado y colocado en la coleccion de menu, de esta forma desligamos del menu.
                }
            }

            catch (IndexOutOfRangeException)  //excepcion cuando no encuentra registro en la base de datos caja.
            {
                MessageBox.Show("Aún no se han abierto ninguna caja, por lo tanto no puede registrar gastos.", "INFORMES", MessageBoxButtons.OK, MessageBoxIcon.Information);

                this.Close(); //Cerramos el form instanciado y colocado en la coleccion de menu, de esta forma desligamos del menu.
            
            }

            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

        private void cargarGrillaGastos()  //carga la grilla de gastos.
        {
            if (!refrescarCenterQuimDs)  //no hace falta que actualice el CenterQuimDs
            {
                //CARGAR GRILLA CON DATOS. USAR DIRECTAMENTE LOS CenterQuimDs y GastosTa;
                llenar_dg();
            }
            else
            {
                try
                {
                    actualizarCenterQuimDs();
                    ///CARGAR GRILLA CON DATOS. USAR DIRECTAMENTE LOS CenterQuimDs y GastosTa;
                    llenar_dg();
                }

                catch (IndexOutOfRangeException)
                {
                    //Puede llegar a ocurrir una excepción de este tipo, no se hace nada, ya que puede no haber gastos para la caja.
                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa./n/n Comuniquese con su desarrollador para solucionar el problema/n/n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error grave se cierra el formulario 
                    this.Close();
                }
            }
        }

        private void actualizarCenterQuimDs()
        {
            //ACTUALIZAR EL ATRIBUTO CenterQuimDs
            //GastosTa.FillByProductos1(...);
            GastosTa.FillByCodigoCaja(centerQuimDs.Gastos, this.nroCaja);

            refrescarCenterQuimDs = false;  //una vez que se actualizo colocamos a false.

        }

        private void llenar_dg()//llena el datagride con los datos de la consulta
        {
            dgvGastos.Rows.Clear();

            for (int i = 0; i < centerQuimDs.Gastos.Rows.Count; i++)
            {
                dgvGastos.Rows.Add(centerQuimDs.Gastos[i].nroGasto, centerQuimDs.Gastos[i].concepto, centerQuimDs.Gastos[i].monto);
            }

        }

        private string obtenerFechaActual()  //Dato necesario para la apertura de una caja.
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }

        private int obtenerCodUsuarioActual()  //Dato necesario para la apertura de una caja
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getCodUsuario();
        }

        private void btnAgregar_Click(object sender, EventArgs e)  //captura el evento de presion sobre el botón agregar
        {
            if (estFormulario == "estEsperandoOperacion")
            {
                estAgregar();
            }
            else
            {
                estEsperandoOperacion();
            }
        }

        private void btnEditar_Click(object sender, EventArgs e) //captura el evento de presion sobre el botón editar
        {
            if (estFormulario == "estEsperandoOperacion")
            {
                estEditar();
            }
            else
            {
                estEsperandoOperacion();
            }
        }

        private void btnEliminar_Click(object sender, EventArgs e) //captura el evento de presion sobre el botón eliminar.
        {
            DialogResult result = MessageBox.Show("¿Desea eliminar el gasto seleccionado?.", "CONFIRMACION", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {
                try
                {

                    Double montoEliminado = Convert.ToInt32(dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[2].Value);

                    //SE ELIMINA EL GASTO DE LA FILA ACTUAL EN LA TABLA GASTOS, ELIMINACION LOGICA
                    GastosTa.UpdateQueryEliminarGasto(false, Convert.ToInt32(dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[0].Value));

                    //SE INCREMENTA LA CAJA POR EL MONTO DEL GASTO
                    this.EliminacionGastoCajaActual(montoEliminado);

                    MessageBox.Show("¡El gasto se ha eliminado con exito.!", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    refrescarCenterQuimDs = true;

                    estEsperandoOperacion();
                }

                catch (IndexOutOfRangeException)
                {
                    //Se informe que no se encontró nada porque el argumento de busqueda esta fuera del rango.
                    MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    //Si llega a ocurrir algún error grave se cierra el formulario
                    this.Close();
                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa./n/n Comuniquese con su desarrollador para solucionar el problema/n/n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error grave se cierra el formulario 
                    this.Close();
                }

            }
        }

        private void btnRegistrar_Click(object sender, EventArgs e) //captura el evento de presion sobre el botón registrar.
        {
            procesar();
        }

        private void procesar()  //método que se ejecuta una edición o un alta de un gasto.
        {
            if (estFormulario == "estAgregar") //estado agregar
            {
                if (formularioValido())
                {
                    if (fondosSuficienteAgregar(Convert.ToDouble(txtImporte.Text)))
                    {
                        agregarGasto();

                    }
                    else
                    {
                        MessageBox.Show("¡No puede realizar esta operación. \n\nEl monto del gasto supera el monto disponible en la caja.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                    }

                }
                else
                {
                    informarExistenciaError();
                }

            }
            else  //estado editar
            {
                if (formularioValido())
                {
                    if (fondosSuficienteEditar(Convert.ToDouble(txtImporte.Text)))
                    {
                        editarGasto();

                    }
                    else
                    {
                        MessageBox.Show("¡No puede realizar esta operación. \n\nEl monto del gasto supera el monto disponible en la caja.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                    }

                }
                else
                {
                    informarExistenciaError();
                }
            }
        }

        private void editarGasto()
        {
            DialogResult result = MessageBox.Show("¿Está seguro que modificar el gasto?.", "CONFIRMACION EDICION DE GASTO", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {
                try
                {
                    EliminacionGastoCajaActual(Convert.ToDouble(dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[2].Value));  //actualiza la caja por el monto del gasto.

                    //Consulta de UPDATE,  A LOS DATOS DE TIPO STRING SE LE SACA LOS ESPACIOS BLANCOS AL PRINICIPIO Y FINAL, LUEGO SE CONVIERTE A MAYUSCULA.
                    //adaptadorGastos.InsertQueryGastos(UCase(Trim(txtNombreUsuario.Text)), UCase(Trim(txtDescripcion.Text)), CInt(txtStock.Text), CDbl(txtPrecioCosto.Text), CDbl(txtPrecioVenta.Text), cbPesable.Checked)

                    GastosTa.FillByNroGasto(centerQuimDs.Gastos, Convert.ToInt32(dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[0].Value));

                    centerQuimDs.Gastos[0].concepto = txtConcepto.Text.Trim().ToUpper();
                    centerQuimDs.Gastos[0].monto = Math.Round(Convert.ToDouble(txtImporte.Text), 2);
                    GastosTa.Update(centerQuimDs.Gastos);

                    agregarGastoCaja(Convert.ToDouble(txtImporte.Text));  //se agrega el nuevo gasto a la caja actual.

                    //Se muestra un mje de confirmación.
                    MessageBox.Show("Gasto editado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);


                    refrescarCenterQuimDs = true; //Se hizo una modificación a la base de datos.

                    estEsperandoOperacion(); //Luego de insertar un usuario se vuelve al estado esperando operación
                }

                catch (IndexOutOfRangeException)
                {
                    //Se informe que no se encontró nada porque el argumento de busqueda esta fuera del rango.
                    MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    //Si llega a ocurrir algún error en estado agregar
                    estEsperandoOperacion();
                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa. /n /n Comuniquese con su desarrollador para solucionar el problema /n /n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.estEsperandoOperacion();
                }

            }
        }


        private void agregarGasto()
        {
            DialogResult result = MessageBox.Show("¿Está seguro que desea ingresar el gasto?.", "CONFIRMACION INGRESO DE GASTO", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {
                try
                {
                    //CONSULTA DE INSERT EN TABLA GASTOS, A LOS DATOS DE TIPO STRING SE LE SACA LOS ESPACIOS BLANCOS AL PRINICIPIO Y FINAL, LUEGO SE CONVIERTE A MAYUSCULA.
                    //adaptadorGastos.InsertQueryGastos(,...,...,)

                    GastosTa.InsertQueryGastos(this.nroCaja, Convert.ToDateTime(obtenerFechaActual()), this.turno, txtConcepto.Text.Trim().ToUpper(), Convert.ToDecimal(txtImporte.Text), obtenerCodUsuarioActual(), true);

                    agregarGastoCaja(Convert.ToDouble(txtImporte.Text));  //actualiza la caja por el monto del gasto.

                    //Se muestra un mje de confirmación.
                    MessageBox.Show("Gasto ingresado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);


                    refrescarCenterQuimDs = true; //Se hizo una modificación a la base de datos.

                    estEsperandoOperacion(); //Luego de insertar un usuario se vuelve al estado esperando operación
                }

                catch (IndexOutOfRangeException)
                {
                    //Se informe que no se encontró nada porque el argumento de busqueda esta fuera del rango.
                    MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    //Si llega a ocurrir algún error en estado agregar
                    estEsperandoOperacion();
                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa. /n /n Comuniquese con su desarrollador para solucionar el problema /n /n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.estEsperandoOperacion();
                }

            }
        }



        private bool formularioValido()  //valida que los txtConcepto y txtImporte sean 
        {
            validarConcepto();

            validarImporte();


            if ((errorProvider1.GetError(txtConcepto) == "") && (errorProvider1.GetError(txtImporte) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarConcepto()
        {
            if (txtConcepto.Text.Trim() == "")
            {
                errorProvider1.SetError(txtConcepto, "Concepto: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(txtConcepto, new ValidarDatos().validarLongitud("Concepto:", txtConcepto.Text, 50));

            }
        }

        private void validarImporte()
        {
            if (txtImporte.Text.Trim() == "")
            {
                errorProvider1.SetError(txtImporte, "Importe: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(txtImporte, new ValidarDatos().validarMoneda("Importe:", txtImporte.Text));
            }
        }

        private bool fondosSuficienteAgregar(Double unMonto)  //verifica que exista monto en la caja para realizar un gasto
        {
            try
            {
                CajasTa.FillByNroCaja(centerQuimDs.Cajas, this.nroCaja);   //se obtienen los datos de la caja

                if (centerQuimDs.Cajas[0].cajaFinal >= unMonto)
                {
                    return true;
                }
                else
                {
                    return false;
                }

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa./n/n Comuniquese con su desarrollador para solucionar el problema/n/n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();

                return false;

            }
        }

        private bool fondosSuficienteEditar(double unMontoNuevo) //verifica que exista monto en la caja para editar un gasto
        {
            try
            {
                CajasTa.FillByNroCaja(centerQuimDs.Cajas, this.nroCaja);   //se obtienen los datos de la caja actual 

                GastosTa.FillByNroGasto(centerQuimDs.Gastos, Convert.ToInt32(dgvGastos.Rows[dgvGastos.CurrentRow.Index].Cells[0].Value)); //se obtienen el monto del gasto sin editar

                Double cajaFinalSinGastoViejo = centerQuimDs.Cajas[0].cajaFinal + centerQuimDs.Gastos[0].monto;


                if (cajaFinalSinGastoViejo >= unMontoNuevo)
                {
                    return true;
                }
                else
                {
                    return false;
                }

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa./n/n Comuniquese con su desarrollador para solucionar el problema/n/n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();

                return false;

            }
        }

        private void agregarGastoCaja(double unMontoGasto)
        {
            CajasTa.FillByNroCaja(centerQuimDs.Cajas, this.nroCaja);   //se obtienen los datos de la caja 

            centerQuimDs.Cajas[0].gastos = centerQuimDs.Cajas[0].gastos + unMontoGasto;  //aumenta el campo gasto por el monto.

            centerQuimDs.Cajas[0].cajaFinal = centerQuimDs.Cajas[0].cajaFinal - unMontoGasto; //disminuye la caja final por el monto

            CajasTa.Update(centerQuimDs.Cajas);
        }

        private void EliminacionGastoCajaActual(Double unMonto)  // los procesos que se lleva a cabo en la caja cuando se elimina un gasto.
        {

            CajasTa.FillByNroCaja(centerQuimDs.Cajas, this.nroCaja);   //se obtienen los datos de la caja 

            centerQuimDs.Cajas[0].gastos = centerQuimDs.Cajas[0].gastos - unMonto;  //dismuniye el campo gasto por el monto.

            centerQuimDs.Cajas[0].cajaFinal = centerQuimDs.Cajas[0].cajaFinal + unMonto; //aumenta la caja final por el monto

            CajasTa.Update(centerQuimDs.Cajas);

        }

    }
}
